package com.kite.ossServer;

import android.webkit.JavascriptInterface;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;

public class Node {
    public Map<String,Node> childNodes;
    public Map<String,Trop> trops;
    public boolean isExt;
    public String nodeN;

    public Node(boolean flag,String nodeN) {
        this.isExt=flag;
        this.nodeN=nodeN;
        this.childNodes = new HashMap<String,Node>();
        this.trops = new HashMap<String,Trop>();
    }
    public Node(String nodeN){
        this.isExt=true;
        this.nodeN=nodeN;
        this.childNodes = new HashMap<String,Node>();
        this.trops = new HashMap<String,Trop>();
    }

    // 判断当前节点是否有效
    @JavascriptInterface
    public boolean Exted(){
        return isExt;
    }

    // 清理子节点
    @JavascriptInterface
    public String clear(){
        try {
            this.childNodes.clear();
            this.trops.clear();

            JSONObject result = new JSONObject();
            result.put("success", true);
            result.put("message", "节点清理成功");
            result.put("childCount", this.childNodes.size());
            result.put("tropCount", this.trops.size());

            return result.toString();
        } catch (Exception e) {
            return "{\"success\":false,\"error\":\"清理节点失败: " + escapeJson(e.getMessage()) + "\"}";
        }
    }

    // 获取节点的名字
    @JavascriptInterface
    public String getNodeN(){
        return this.nodeN;
    }

    // 加入属性
    public Node appendTrop(String tropName,Trop trop){
        if(trops.containsKey(tropName)){
            deleteTrop(tropName);
        }
        this.trops.put(tropName,trop);
        return this;
    }

    public Node appendTrop(String tropName,String tropValue){
        if(trops.containsKey(tropName)){
            deleteTrop(tropName);
        }
        this.trops.put(tropName,new Trop(tropName,tropValue));
        return this;
    }

    public Node appendTrop(String tropName, Object tropValue){
        appendTrop(tropName, new Trop(tropName, tropValue));
        return this;
    }

    // 加入节点
    public Node appendNode(String nodeName,Node node){
        if(childNodes.containsKey(nodeName)){
            deleteNode(nodeName);
        }
        this.childNodes.put(nodeName,node);
        return node;
    }

    public Node appendNode(String nodeName){
        if(childNodes.containsKey(nodeName)){
            deleteNode(nodeName);
        }
        Node nd = new Node(nodeName);
        this.childNodes.put(nodeName,nd);
        return nd;
    }

    // 获得所有的node节点
    public ArrayList<Node> getNodes(){
        ArrayList<Node> nodes = new ArrayList<>();
        this.childNodes.forEach((key,value)->{
            nodes.add(value);
        });
        return nodes;
    }

    // 获得所有的Trop节点
    public ArrayList<Trop> getTrops(){
        ArrayList<Trop> troplist = new ArrayList<>();
        this.trops.forEach((key,value)->{
            troplist.add(value);
        });
        return troplist;
    }

    // 删除属性
    public boolean deleteTrop(String tropName){
        if(trops.containsKey(tropName)){
            trops.remove(tropName);
            return true;
        }
        return false;
    }

    // 删除节点
    public boolean deleteNode(String nodeName){
        if(childNodes.containsKey(nodeName)){
            childNodes.remove(nodeName);
            return true;
        }
        return false;
    }

    // 查询Node
    public List<Node> findNodes(Predicate<Node> condition) {
        List<Node> result = new ArrayList<>();
        findNodesRecursive(this, condition, result);
        return result;
    }
    public void findNodesRecursive(Node currentNode, Predicate<Node> condition, List<Node> result) {
        if (condition.test(currentNode)) {
            result.add(currentNode);
        }
        currentNode.childNodes.values().forEach(child -> findNodesRecursive(child, condition, result));
    }

    // 查询Trop
    public List<Trop> findTrops(Predicate<Trop> condition) {
        List<Trop> result = new ArrayList<>();
        findTropsRecursive(this, condition, result);
        return result;
    }
    public void findTropsRecursive(Node currentNode, Predicate<Trop> condition, List<Trop> result) {
        currentNode.trops.values()
                .stream()
                .filter(condition)
                .forEach(result::add);
        currentNode.childNodes.values().forEach(child -> findTropsRecursive(child, condition, result));
    }

    // 是否存在Node
    public boolean containsNode(String nodeName) {
        return childNodes.containsKey(nodeName) && childNodes.get(nodeName).Exted();
    }

    // 是否存在Trop
    public boolean containsTrop(String tropName) {
        return trops.containsKey(tropName) && trops.get(tropName).Exted();
    }

    // 批量加入Trop
    public boolean appendTrops(Map<String, String> tropMap) {
        for (Map.Entry<String, String> entry : tropMap.entrySet()) {
            appendTrop(entry.getKey(), entry.getValue());
        }
        return true;
    }

    // 复制当前Node
    public Node deepCopy(Node original) {
        Node copy = new Node(original.isExt, original.nodeN);
        original.trops.forEach((key, trop) -> {
            copy.appendTrop(key, new Trop(trop.tropName, trop.tropValue));
        });
        original.childNodes.forEach((key, node) -> {
            copy.appendNode(key, deepCopy(node));
        });
        return copy;
    }

    // 批量加入Node
    public boolean appendNodes(Map<String, Node> nodeMap) {
        for (Map.Entry<String, Node> entry : nodeMap.entrySet()) {
            appendNode(entry.getKey(), entry.getValue());
        }
        return true;
    }

    // 链式添加Trop
    public Node withTrop(String name, String value) {
        appendTrop(name, value);
        return this;
    }

    // 链式添加Node
    public Node withNode(String name, Node node) {
        appendNode(name, node);
        return this;
    }

    public Node withNode(String name){
        appendNode(name);
        return this;
    }

    // 获得属性
    public Trop getTrop(String tropName){
        if(trops.containsKey(tropName)){
            return trops.get(tropName);
        }
        return new Trop();
    }

    // 直接获取Trop的值
    public String getTropValue(String tropName){
        if(trops.containsKey(tropName)){
            return trops.get(tropName).getTropValue();
        }
        return "";
    }

    // 进入节点环境
    public Node joinPath(String path) {
        String[] segments = path.split("\\.");
        Node current = this;
        for (String segment : segments) {
            if (segment.isEmpty()) continue;
            Node next = current.join(segment);
            if (!next.Exted()) {
                return new Node(false, "");
            }
            current = next;
        }
        return current;
    }

    // 进入节点
    public Node join(String nodeName){
        if(childNodes != null && childNodes.containsKey(nodeName)){
            return childNodes.get(nodeName);
        }
        return new Node(false,"");
    }

    // 解析jsonArr
    @JavascriptInterface
    public String parseJSONFromArray(String jsonString, String targetNodeName) {
        try {
            if (jsonString == null || jsonString.trim().isEmpty()) {
                return createErrorResponse("JSON字符串不能为空");
            }

            if (targetNodeName == null || targetNodeName.trim().isEmpty()) {
                targetNodeName = "ROOT";
            }

            JSONArray jsonArr = new JSONArray(jsonString);
            Node target = new Node(true, targetNodeName);

            for (int i = 0; i < jsonArr.length(); i++){
                try {
                    Object val = jsonArr.get(i);
                    String item = String.valueOf(i);
                    if(val instanceof JSONObject){
                        JSONObject jsonObj = (JSONObject) val;
                        target.appendNode(item, parseJSONObject(jsonObj, new Node(true, item)));
                    } else if(val instanceof JSONArray) {
                        JSONArray jsonarr = (JSONArray) val;
                        target.appendNode(item, parseJSONObject(jsonarr, new Node(true, item)));
                    } else {
                        target.appendTrop(item, new Trop(item, String.valueOf(val)));
                    }
                } catch (Exception e) {
                    android.util.Log.w("Node", "解析JSON数组元素失败: " + i, e);
                    // 继续处理其他元素
                }
            }

            JSONObject result = new JSONObject();
            result.put("success", true);
            result.put("nodeName", target.getNodeN());
            result.put("tropCount", target.TropLength());
            result.put("childCount", target.nodeLength());

            return result.toString();
        } catch (Exception e) {
            return createErrorResponse("解析JSON数组失败: " + e.getMessage());
        }
    }

    // 解析JSONObject
    private Node parseJSONObject(Object jsonObj, Node target) {
        try {
            if (jsonObj instanceof JSONObject) {
                JSONObject json = (JSONObject) jsonObj;
                for (java.util.Iterator<String> it = json.keys(); it.hasNext();) {
                    String keyName = it.next();
                    Object value = json.get(keyName);
                    if (value instanceof JSONObject) {
                        target.appendNode(keyName, parseJSONObject(value, new Node(true, keyName)));
                    } else if (value instanceof JSONArray) {
                        target.appendNode(keyName, parseJSONObject(value, new Node(true, keyName)));
                    } else {
                        target.appendTrop(keyName, new Trop(keyName, String.valueOf(value)));
                    }
                }
            } else if (jsonObj instanceof JSONArray) {
                JSONArray jsonArr = (JSONArray) jsonObj;
                for (int i = 0; i < jsonArr.length(); i++) {
                    Object val = jsonArr.get(i);
                    String item = String.valueOf(i);
                    if (val instanceof JSONObject) {
                        target.appendNode(item, parseJSONObject(val, new Node(true, item)));
                    } else if (val instanceof JSONArray) {
                        target.appendNode(item, parseJSONObject(val, new Node(true, item)));
                    } else {
                        target.appendTrop(item, new Trop(item, String.valueOf(val)));
                    }
                }
            }
            return target;
        } catch (Exception e) {
            android.util.Log.e("Node", "解析JSON对象失败", e);
            return new Node(false, "ERROR");
        }
    }

    // 解析为json
    @JavascriptInterface
    public String toJSON() {
        try {
            Object json = nodeToJson(this);
            if (json instanceof JSONObject) {
                return ((JSONObject) json).toString(2);
            }
            // 理论上根节点一定是 JSONObject
            return new JSONObject().toString();
        } catch (Exception e) {
            android.util.Log.e("Node", "转换为JSON失败", e);
            return "{\"error\":\"JSON转换失败\"}";
        }
    }

    // nodeTree解析为jsonobject
    private Object nodeToJson(Node node) {
        try {
            if (!node.trops.isEmpty()) {
                return handleAsObject(node);
            }
            // 检测是否为数组：所有key必须是连续数字
            boolean isArray = !node.childNodes.isEmpty();
            for (int i = 0; i < node.childNodes.size(); i++) {
                if (!node.childNodes.containsKey(String.valueOf(i))) {
                    isArray = false;
                    break;
                }
            }
            return isArray ? handleAsArray(node) : handleAsObject(node);
        } catch (Exception e) {
            android.util.Log.e("Node", "节点转换JSON失败", e);
            return new JSONObject();
        }
    }

    private JSONArray handleAsArray(Node node) {
        try {
            JSONArray array = new JSONArray();
            for (int i = 0, n = node.childNodes.size(); i < n; i++) {
                Node child = node.childNodes.get(String.valueOf(i));
                if (child != null) {
                    Object childJson = nodeToJson(child);
                    if (childJson instanceof JSONObject) {
                        array.put(childJson);
                    } else {
                        array.put(JSONObject.NULL);
                    }
                } else {
                    array.put(JSONObject.NULL);
                }
            }
            return array;
        } catch (Exception e) {
            android.util.Log.e("Node", "数组转换JSON失败", e);
            return new JSONArray();
        }
    }

    private JSONObject handleAsObject(Node node) {
        try {
            JSONObject obj = new JSONObject();
            // 处理属性
            for (Map.Entry<String, Trop> entry : node.trops.entrySet()) {
                String key = entry.getKey();
                Trop trop = entry.getValue();
                try {
                    obj.put(key, parseValue(trop.getTropValue()));
                } catch (JSONException e) {
                    try {
                        obj.put(key, trop.getTropValue());
                    } catch (JSONException ex) {
                        android.util.Log.w("Node", "属性JSON添加失败: " + key, ex);
                    }
                }
            }
            // 处理子节点
            for (Map.Entry<String, Node> entry : node.childNodes.entrySet()) {
                String key = entry.getKey();
                Node childNode = entry.getValue();
                try {
                    Object childJson = nodeToJson(childNode);
                    if (childJson instanceof JSONObject || childJson instanceof JSONArray) {
                        obj.put(key, childJson);
                    }
                } catch (Exception e) {
                    android.util.Log.w("Node", "子节点JSON添加失败: " + key, e);
                }
            }
            return obj;
        } catch (Exception e) {
            android.util.Log.e("Node", "对象转换JSON失败", e);
            return new JSONObject();
        }
    }

    // 解析Trop的值
    public Object parseValue(String raw) {
        if (raw == null) return JSONObject.NULL;
        if ("true".equalsIgnoreCase(raw)) return true;
        if ("false".equalsIgnoreCase(raw)) return false;
        if ("null".equalsIgnoreCase(raw)) return JSONObject.NULL;
        try {
            if (!raw.startsWith("0") || raw.length() == 1) {
                long l = Long.parseLong(raw);
                if (l <= Integer.MAX_VALUE && l >= Integer.MIN_VALUE) return (int) l;
                return l;
            }
        } catch (NumberFormatException ignored) {
            // TODO.
        }
        try {
            double d = Double.parseDouble(raw);
            if ((d + "").equals(raw)) return d;
        } catch (NumberFormatException ignored) {
            // TODO.
        }
        return raw;
    }

    // 解析json
    public Node parseJSON(JSONObject json,Node target) throws Exception {
        for (Iterator<String> it = json.keys(); it.hasNext();) {
            String keyName = it.next();
            Object value = json.get(keyName);
            if (value instanceof JSONObject) {
                JSONObject jsonObj = (JSONObject)value;
                target.appendNode(keyName,parseJSON(jsonObj,new Node(true,keyName)));
            } else if (value instanceof JSONArray) {
                JSONArray jsonArr = (JSONArray) value;
                target.appendNode(keyName,parseJSON(jsonArr,new Node(true,keyName)));
            } else {
                target.appendTrop(keyName,new Trop(keyName,String.valueOf(value)));
            }
        }
        return target;
    }

    // 获得当前节点所有的属性数量
    public int TropLength(){
        return this.trops.size();
    }

    // 获取当前节点的数量
    public int nodeLength(){
        return this.childNodes.size();
    }

    // ============ 辅助方法 ============

    /**
     * 转义JSON字符串中的特殊字符
     */
    private String escapeJson(String value) {
        if (value == null) {
            return "";
        }
        return value.replace("\\", "\\\\")
                   .replace("\"", "\\\"")
                   .replace("\b", "\\b")
                   .replace("\f", "\\f")
                   .replace("\n", "\\n")
                   .replace("\r", "\\r")
                   .replace("\t", "\\t");
    }

    @Override
    public String toString() {
        String format = String.format("Node{name='%s', tropCount=%d, childCount=%d}", nodeN, TropLength(), nodeLength());
        return format;
    }
}
